<?php
Zend_Loader::loadClass('Lead_Event_Observable_Abstract');

Zend_Loader::loadClass('Lead_EDO_Datatype_Field_Interface');
Zend_Loader::loadClass('Lead_EDO_Datatype_Field_Value');
Zend_Loader::loadClass('Lead_EDO_Datatype_Field_Relation');

Zend_Loader::loadClass('Lead_EDO_Datatype_Validator');

/**
 * @package EDO
 * @subpackage Core
 *
 */
abstract class Lead_EDO_Object_Abstract extends Lead_Event_Observable_Abstract
{

    protected $_fieldarray = array();

    /**
     * Finder
     *
     * @var Lead_EDO_Finder
     */
    protected $_finder;

	/**
	 * Handler
	 *
	 * @var Lead_EDO_Handler_Interface
	 */
	private $_handler;

	private $_isFetched = false;


	public function __construct(Lead_EDO_Handler_Interface $handler)
	{
		$this->_handler = $handler;
	    $this->_initialize();
	}
	
	
	public function __toString()
	{
	    $output = '';
	    $output .= "EDO;class:{$this->getClass()};id:";
	    $output .= ($this->id) ? $this->id : 'null';
	    $output .= '';
	    
	    return $output;
	}
		
	
	protected function _initialize()
	{
	    $type = $this->getType();
	    
	    $datatypeArr = $this->getType()->getRawFields();
	    
	    // $datatypeArr = array_merge($this->getType()->getRawFields(), $this->getType()->getRelations());
	    
	    foreach($datatypeArr as $fieldName => $fieldData)
		{
		    $datatype = $fieldData['DATA_TYPE'];
    		$datatypeObj = new Lead_EDO_Datatype_Field_Value($this, $fieldData); 	
    		$this->_fieldarray[$fieldName] = $datatypeObj;
		}
		
		$relations = $type->getRelations();
		
		/*
		print "<pre>";
		print_r($relations);
		
		die();
		*/

		foreach($relations as $fieldName => $fieldData) {
            $datatypeObj = new Lead_EDO_Datatype_Field_Relation($this, $fieldData);
            $this->_fieldarray[$fieldName] = $datatypeObj;	
		}
		
	}
	
	
	
	/**
	 * Enter description here...
	 *
	 * @return boolean Success or not
	 */
	public function insert()
	{
		return $this->getHandler()->insert($this);
	}
	
	
	
	protected function __call($method, $args)
	{
        if($this->fieldExists($method))
            return $this->getFieldObject($method);

        throw new Lead_EDO_Exception("'{$method}' field object or method does not exist and was not trapped in __call");

	}
	
	
	
	/**
	 * Overloads the getting of class properties in the fieldarray.
	 *
	 * @param string $key Field name
	 * @return mixed Field value
	 */
	protected function __get($key)
	{
		if(key_exists($key, $this->_fieldarray))
		{
			return $this->getField($key);
		}
		throw new Lead_EDO_Exception("Field '{$key}' does not exist");
	}

	/**
	 * Overloads the setting of class properties in the fieldarray.
	 *
	 * @param string $key Field name
	 * @param mixed $value Field value
	 * @return boolean Success or not.
	 */
	protected function __set($key, $value)
	{
		if(key_exists($key, $this->_fieldarray))
		{
			return $this->setField($key, $value);
		}
		throw new Lead_EDO_Exception("Field '{$key}' does not exist");
	}
	
	/**
	 * Saves the dataobject.
	 *
	 * @param integer $clear If 1, ensures that a new id is assigned. Wooooot?
	 * @return boolean Success or not.
	 */
	public function save()
	{
		return $this->getHandler()->save($this);
	}



	/**
	 * Deletes the dataobject. There is no coming back.
	 *
	 * @return boolean Success or not.
	 */
	function delete()
	{
		return $this->getHandler()->delete($this);
	}

	
	
	
	
	
	
	
	
	
	
	
	/* AFTER THIS NOT REVIEWED... */






	/**
	 * Sets masses of fields from a raw associative array.
	 *
	 * @param array $fieldarray
	 */
	public function setFields($fieldarray, $validate = true)
	{
	    foreach($fieldarray as $fieldkey => &$fieldvalue)
		{
			if(key_exists($fieldkey, $this->_fieldarray))
			{
				$this->setField($fieldkey, $fieldvalue, $validate);
			}
		}
	}


	/**
	 * Returns the EDO class of the dataobject.
	 *
	 * @return string
	 */
	public function getClass()
	{
		return get_class($this);
	}


	/**
	 * Sets a field value.
	 *
	 * @param string $key Field name
	 * @param mixed $value Field value
	 * @return boolean Success or not
	 */
	public function setField($key, $value, $validate = true)
	{	    	    
	    $success = $this->getFieldObject($key)->setValue($value, $validate);
    	return ($success === false) ? false : true;
	}

	/**
	 * Returns the value of a field.
	 *
	 * @param string $key Field name
	 * @return mixed Field value
	 */
	public function getField($key)
	{
	    return $this->getFieldObject($key)->getValue();

	    // return $this->_fieldarray[$key]->getValue();
	}


	/**
	 * Returns the field object for a field.
	 *
	 * @param string $key Field name
	 * @return Datatype_base Datatype object
	 */
	public function getFieldObject($key)
	{
		if(isset($this->_fieldarray[$key]))
	       return $this->_fieldarray[$key];

	    return false;
	}


	public function getFieldsType($fieldName)
	{
		return $this->getFieldObject($fieldName)->getType();
	}



	/**
	 * Returns a relation from relationarray.
	 *
	 * @param string $key Relation name
	 * @return unknown
	 */
	public function getRelation($key)
	{
		return $this->getType()->getRelation($key);
	}

	public function getFieldObjects()
	{
	    return $this->_fieldarray;
	}


	public function getRelationObjects()
	{
	    $relArr = array();
	    foreach($this->getType()->getRelations() as $relation)
	    {
	        $relArr[] = $this->getFieldObject($relation['name']);
	    }
	    return $relArr;
	}







	/**
	 * Returns object's Finder object.
	 *
	 * @return Lead_EDO_Finder
	 */
	public function getFinder()
	{
        Zend_Loader::loadClass('Lead_EDO_Finder');
	    return new Lead_EDO_Finder($this);
	}



	public function getHandler()
	{
		return $this->_handler;
	}



	public function fieldExists($fieldName)
	{
	    return (key_exists($fieldName, $this->_fieldarray)) ? true : false;
	}




	/**
	 * Gets a new EDO of object's class. If id is defined, the new object is fetched.
	 *
	 * @param integer $id
	 * @return EDO_object_basic
	 */
	public function get()
	{
	    $obj = $this->getHandler()->get($this->getClass());
	    return $obj;
	}






	/**
	 * Fetches a dataobject.
	 *
	 * @param unknown_type $id
	 */
	function fetch($id)
	{
	    return $this->getHandler()->fetch($id, $this->getClass());
    }


	/**
	 * Sets object's fetched state.
	 *
	 * @param boolean $fetchedStatus true or false
	 */
	public function setFetched($fetchedStatus)
	{
		$this->_isFetched = $fetchedStatus;
	}

	/**
	 * Returns true if object state is fetched, false if not
	 *
	 * @return boolean true or false
	 */
	public function isFetched()
	{
		return $this->_isFetched;
	}


	/**
	 * Returns a collection.
	 *
	 * @param unknown_type $keys
	 * @param unknown_type $collectionType
	 * @return unknown
	 */
	public function collection($keys = array(), $collectionType = 'basic')
	{
		return $this->getHandler()->collection($this->getClass(), $keys, $collectionType);

	}


	/**
	 * Returns dataobjects unique typeid.
	 *
	 * @return integer
	 */
	public function getTypeid()
	{
        return $this->getHandler()->convert($this->getClass());
	}


    public function getType()
    {
        return $this->getHandler()->getType($this);
    }


}
